import turtle
import random
import matplotlib.pyplot as plt
import pandas as pd
import traceback


def draw_square(t, size):
    """绘制正方形"""
    for _ in range(4):
        t.forward(size)
        t.right(90)


def draw_triangle(t, size):
    """绘制三角形"""
    for _ in range(3):
        t.forward(size)
        t.right(120)


def draw_circle(t, radius):
    """绘制圆形"""
    t.circle(radius)


def draw_simple_shapes(screen):
    """绘制简单图形"""
    # 创建画笔
    pen = turtle.Turtle()
    pen.speed(1)  # 设置较慢速度以便观察
    pen.width(2)  # 增加线宽

    # 绘制正方形
    print("正在绘制正方形...")
    pen.penup()
    pen.goto(-150, 50)
    pen.pendown()
    pen.color("red")
    draw_square(pen, 100)

    # 绘制三角形
    print("正在绘制三角形...")
    pen.penup()
    pen.goto(0, 50)
    pen.pendown()
    pen.color("blue")
    draw_triangle(pen, 100)

    # 绘制圆形
    print("正在绘制圆形...")
    pen.penup()
    pen.goto(150, 0)
    pen.pendown()
    pen.color("green")
    draw_circle(pen, 50)

    # 隐藏画笔
    pen.hideturtle()
    print("简单图形绘制完成！")

    # 添加说明文字
    text = turtle.Turtle()
    text.penup()
    text.hideturtle()
    text.goto(0, -150)
    text.write("点击窗口继续", align="center", font=("Arial", 14, "normal"))


def simulate_movement(screen):
    """模拟人和鳄鱼的移动并记录轨迹"""
    # 创建人和鳄鱼的Turtle对象
    person = turtle.Turtle()
    person.shape("circle")
    person.color("blue")
    person.penup()
    person.goto(-200, 0)  # 起点在左侧
    person.pendown()
    person.width(2)  # 增加线宽

    crocodile = turtle.Turtle()
    crocodile.shape("turtle")
    crocodile.color("green")
    crocodile.penup()
    crocodile.goto(200, 0)  # 起点在右侧
    crocodile.pendown()
    crocodile.width(2)  # 增加线宽

    # 添加说明文字
    text = turtle.Turtle()
    text.penup()
    text.hideturtle()
    text.goto(0, -180)
    text.write("模拟移动中...", align="center", font=("Arial", 14, "normal"))

    # 设置屏幕更新选项以提高性能
    screen.tracer(0)

    # 初始化轨迹数据
    trajectory_data = {
        'person': {'x': [person.xcor()], 'y': [person.ycor()]},
        'crocodile': {'x': [crocodile.xcor()], 'y': [crocodile.ycor()]},
        'time': [0]
    }

    # 模拟移动
    time = 0
    max_time = 50  # 减少模拟步数以加快速度

    while time < max_time:
        # 人的移动（随机但有方向性）
        person_angle = person.heading()
        person_angle += random.randint(-30, 30)  # 随机改变方向
        person.setheading(person_angle)
        person.forward(random.randint(5, 10))

        # 鳄鱼的移动（追踪人）
        angle_to_person = crocodile.towards(person)
        crocodile.setheading(angle_to_person)
        crocodile.forward(random.randint(3, 8))

        # 记录轨迹
        trajectory_data['person']['x'].append(person.xcor())
        trajectory_data['person']['y'].append(person.ycor())
        trajectory_data['crocodile']['x'].append(crocodile.xcor())
        trajectory_data['crocodile']['y'].append(crocodile.ycor())
        trajectory_data['time'].append(time + 1)

        # 每5步更新一次屏幕
        if time % 5 == 0:
            screen.update()

        time += 1

    # 最终更新屏幕
    screen.update()

    # 添加完成文字
    text.clear()
    text.goto(0, -180)
    text.write("模拟完成!", align="center", font=("Arial", 14, "normal"))

    # 恢复屏幕更新
    screen.tracer(1)

    return trajectory_data


def save_trajectory_data(trajectory_data, filename='trajectory.csv'):
    """将轨迹数据保存为CSV文件"""
    # 创建DataFrame
    data = {
        'time': trajectory_data['time'],
        'person_x': trajectory_data['person']['x'],
        'person_y': trajectory_data['person']['y'],
        'crocodile_x': trajectory_data['crocodile']['x'],
        'crocodile_y': trajectory_data['crocodile']['y']
    }

    df = pd.DataFrame(data)

    # 保存为CSV文件
    df.to_csv(filename, index=False)
    print(f"\n轨迹数据已保存到 {filename}")

    return df


def visualize_trajectory(trajectory_data):
    """可视化轨迹数据"""
    # 设置支持中文的字体
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
    plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

    plt.figure(figsize=(10, 8))

    # 绘制人的轨迹
    plt.plot(trajectory_data['person']['x'],
             trajectory_data['person']['y'],
             'b-', label='人', linewidth=2)

    # 绘制鳄鱼的轨迹
    plt.plot(trajectory_data['crocodile']['x'],
             trajectory_data['crocodile']['y'],
             'g-', label='鳄鱼', linewidth=2)

    # 标记起点和终点
    plt.plot(trajectory_data['person']['x'][0],
             trajectory_data['person']['y'][0],
             'bo', markersize=10, label='人的起点')

    plt.plot(trajectory_data['person']['x'][-1],
             trajectory_data['person']['y'][-1],
             'b*', markersize=15, label='人的终点')

    plt.plot(trajectory_data['crocodile']['x'][0],
             trajectory_data['crocodile']['y'][0],
             'go', markersize=10, label='鳄鱼的起点')

    plt.plot(trajectory_data['crocodile']['x'][-1],
             trajectory_data['crocodile']['y'][-1],
             'g*', markersize=15, label='鳄鱼的终点')

    # 添加标题和标签
    plt.title('人和鳄鱼的移动轨迹', fontsize=16)
    plt.xlabel('X坐标', fontsize=12)
    plt.ylabel('Y坐标', fontsize=12)
    plt.legend(fontsize=10)
    plt.grid(True, linestyle='--', alpha=0.7)

    # 添加图例说明
    plt.figtext(0.5, 0.01, "蓝色线表示人的移动路径，绿色线表示鳄鱼的追踪路径",
                ha="center", fontsize=10, bbox={"facecolor": "orange", "alpha": 0.2, "pad": 5})

    # 显示图形
    plt.tight_layout()
    plt.show()


def main():
    print("开始执行实验2：Turtle动态可视化数据路径（人与鳄鱼）\n")

    # 初始化Turtle屏幕
    screen = turtle.Screen()
    screen.title("Turtle数据可视化")
    screen.setup(width=800, height=600)
    screen.bgcolor("lightgray")

    try:
        # === 步骤2.1 搭建Turtle环境并画简单图形 ===
        print("\n=== 步骤2.1 搭建Turtle环境并画简单图形 ===")
        draw_simple_shapes(screen)

        # 等待用户点击继续
        print("\n点击Turtle窗口继续...")
        screen.textinput("继续", "按确定继续")

        # 清除当前屏幕内容
        screen.clear()
        screen.bgcolor("lightyellow")
        screen.title("Turtle数据可视化 - 移动模拟")

        # === 步骤2.2 模拟移动并记录轨迹 ===
        print("\n=== 步骤2.2 模拟移动并记录轨迹 ===")
        trajectory_data = simulate_movement(screen)

        # 等待用户点击继续
        print("\n点击Turtle窗口继续...")
        screen.textinput("继续", "按确定继续")

        # === 步骤2.3 保存轨迹数据 ===
        print("\n=== 步骤2.3 保存轨迹数据 ===")
        df = save_trajectory_data(trajectory_data)
        print("\n数据基本信息：")
        print(df.head())

        # === 步骤2.4 可视化轨迹 ===
        print("\n=== 步骤2.4 可视化轨迹 ===")
        visualize_trajectory(trajectory_data)

        print("\n程序执行完毕！")

    except Exception as e:
        print(f"\n程序出错: {e}")
        traceback.print_exc()
    finally:
        # 安全地关闭屏幕
        if 'screen' in locals() and screen is not None:
            try:
                # 检查窗口是否仍然存在
                if hasattr(screen, '_root') and screen._root is not None:
                    screen.bye()
            except Exception:
                pass  # 忽略关闭过程中可能出现的任何异常
if __name__ == "__main__":
    main()
